const connectBtn = document.getElementById('connectBtn');
const disconnectBtn = document.getElementById('disconnectBtn');
const sendBtn = document.getElementById('sendBtn');
const cmdInput = document.getElementById('cmdInput');
const messagesArea = document.getElementById('messagesArea');
const addPairBtn = document.getElementById('addPairBtn');
const keyValuePairs = document.getElementById('keyValuePairs');

let websocket;

connectBtn.addEventListener('click', function() {
    const serverUrl = 'ws://localhost:8878/im';
    websocket = new WebSocket(serverUrl);
    websocket.binaryType = 'arraybuffer';
    websocket.onopen = () => updateStatus("Connected");
    websocket.onmessage = event => handleMessage(event);
    websocket.onerror = () => updateStatus("WebSocket error");
    websocket.onclose = () => updateStatus("Disconnected");
    connectBtn.disabled = true;
    disconnectBtn.disabled = false;
    sendBtn.disabled = false;
});

disconnectBtn.addEventListener('click', () => websocket && websocket.close());

sendBtn.addEventListener('click', () => {
    const command = parseInt(cmdInput.value);
    const jsonObject = {};
    document.querySelectorAll('.keyInput').forEach((keyElement, index) => {
        const valueElement = document.querySelectorAll('.valueInput')[index];
        jsonObject[keyElement.value] = valueElement.value;
    });
    if (!isNaN(command) && websocket) {
        const packet = buildPacket(command, jsonObject);
        const encodedData = encodePacket(packet);
        websocket.send(encodedData);
        messagesArea.value += 'Sent: ' + JSON.stringify(jsonObject) + '\n';
        cmdInput.value = '';
        document.querySelectorAll('.keyInput').forEach(input => input.value = '');
        document.querySelectorAll('.valueInput').forEach(input => input.value = '');
    }
});

addPairBtn.addEventListener('click', () => {
    const newPairHTML = `Key: <input type="text" class="keyInput" placeholder="Enter Key" />
                         Value: <input type="text" class="valueInput" placeholder="Enter Value" /><br>`;
    keyValuePairs.insertAdjacentHTML('beforeend', newPairHTML);
});

function buildPacket(command, jsonObject) {
    return {
        command: command,
        message: jsonObject
    };
}

function encodePacket(packet) {
    const buffer = new ArrayBuffer(1024);
    const dataView = new DataView(buffer);
    let offset = 0;
    dataView.setInt32(offset, 0x12345678); offset += 4;
    dataView.setUint8(offset, 1); offset += 1;
    dataView.setUint8(offset, 1); offset += 1;
    dataView.setUint8(offset, packet.command); offset += 1;
    const encoder = new TextEncoder();
    const bodyBytes = encoder.encode(JSON.stringify(packet.message));
    dataView.setInt32(offset, bodyBytes.length); offset += 4;
    bodyBytes.forEach((byte, index) => dataView.setUint8(offset + index, byte));
    offset += bodyBytes.length;
    return buffer.slice(0, offset);
}

function updateStatus(status) {
    messagesArea.value += status + '\n';
}

function handleMessage(event) {
    const data = new DataView(event.data);
    const magicNumber = data.getInt32(0);
    const command = data.getUint8(4);
    const bodyLength = data.getInt32(5);
    const body = new TextDecoder('utf-8').decode(new Uint8Array(event.data, 9, bodyLength));
    messagesArea.value += `Received: Command - ${command}, Message - ${body}\n`;
}